package com.rt.gptnext.common.utils.http;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import com.rt.gptnext.common.utils.SafeUtil;
import com.rt.gptnext.common.utils.json.JsonUtil;
import lombok.Getter;
import lombok.Setter;

import java.net.HttpCookie;
import java.util.List;
import java.util.Map;

/**
 * @author gaoyiyang
 **/
public class HttpResponse<T> {

	public static final HttpResponse<byte[]> EMPTY = empty();

	/**
	 * 响应结果
	 */
	@Getter
	private T data;

	/**
	 * 校验结果是否成功
	 */
	@Getter
	@Setter
	private boolean validateSuccess;

	private HttpInfo httpInfo;

	private HttpResponse() {

	}

	public static HttpResponse<byte[]> empty() {
		HttpResponse<byte[]> response = new HttpResponse<>();
		response.httpInfo = new HttpInfo();
		response.data = response.getRaw();
		return response;
	}

	public static HttpResponse<byte[]> create(HttpInfo httpInfo) {
		HttpResponse<byte[]> response = new HttpResponse<>();
		response.httpInfo = httpInfo;
		response.data = response.getRaw();
		return response;
	}

	/**
	 * 是否请求成功
	 *
	 * @return -
	 */
	public boolean isOk() {
		if (httpInfo.getError() != null) {
			return false;
		}
		int statusCode = httpInfo.getStatusCode();
		return statusCode >= 200 && statusCode < 300;
	}

	/**
	 * 获取响应的字符串
	 *
	 * @return -
	 */
	public String getString() {
		return new String(getRaw());
	}

	/**
	 * 获取原始响应
	 *
	 * @return -
	 */
	public byte[] getRaw() {
		return SafeUtil.call(() -> httpInfo.getResponseBody(), new byte[0]);
	}

	/**
	 * 获取json对象
	 *
	 * @return json对象
	 */
	public JSONObject getJsonObject() {
		return get(JSONObject.class);
	}

	/**
	 * 获取json数组
	 *
	 * @return json数组
	 */
	public JSONArray getJsonArray() {
		return get(JSONArray.class);
	}

	/**
	 * 解析返回值为指定类型
	 *
	 * @param targetClass 指定类型
	 * @return 返回指定类型
	 */
	public <T> T get(Class<T> targetClass) {
		if (getRaw() == null) {
			return null;
		}
		if (targetClass == JSONObject.class) {
			return (T) JSON.parseObject(getString());
		}
		if (targetClass == JSONArray.class) {
			return (T) JSON.parseArray(getString());
		}
		return JSON.parseObject(getRaw(), targetClass);
	}

	/**
	 * 解析返回值为指定类型
	 *
	 * @param typeReference 指定类型
	 * @return 返回指定类型
	 */
	public <T> T get(TypeReference<T> typeReference) {
		if (getRaw() == null) {
			return null;
		}
		return JSON.parseObject(getString(), typeReference);
	}

	@Override
	public String toString() {
		return getString();
	}

	/**
	 * 转换data为指定bean类型
	 *
	 * @param typeReference 类型指定
	 * @return -
	 */
	public <TARGET> HttpResponse<TARGET> to(TypeReference<TARGET> typeReference) {
		HttpResponse<TARGET> response = new HttpResponse<>();
		response.httpInfo = this.httpInfo;
		response.data = this.get(typeReference);
		return response;
	}

	/**
	 * 转换data为指定bean类型
	 *
	 * @param targetClass 类型指定
	 * @return -
	 */
	public <TARGET> HttpResponse<TARGET> to(Class<TARGET> targetClass) {
		HttpResponse<TARGET> response = new HttpResponse<>();
		response.httpInfo = this.httpInfo;
		response.validateSuccess = this.validateSuccess;
		response.data = this.get(targetClass);
		return response;
	}

	public String getHeader(String name) {
		Map<String, List<String>> responseHeaders = httpInfo.getResponseHeaders();
		List<String> value = responseHeaders.get(name);
		return CollUtil.getFirst(value);
	}

	public List<HttpCookie> getCookies() {
		String cookie = getHeader("Set-Cookie");
		return HttpCookie.parse(cookie);
	}

	public HttpCookie getCookie(String name) {
		List<HttpCookie> cookies = getCookies();
		if (cookies == null) {
			return null;
		}
		for (HttpCookie cookie : cookies) {
			if (cookie.getName().equals(name)) {
				return cookie;
			}
		}
		return null;
	}

	public HttpInfo getHttpInfo() {
		return this.httpInfo;
	}

	public <T> T getByJsonPath(String jsonPath, Class<T> targetClass) {
		return JsonUtil.getByJsonPath(getRaw(), jsonPath, targetClass);
	}

	public <T> T getByJsonPath(String jsonPath, TypeReference<T> typeReference) {
		return JsonUtil.getByJsonPath(getRaw(), jsonPath, typeReference);
	}
}
